package cn.xshi.log.client.service;

import cn.xshi.log.client.worker.*;
import cn.xshi.log.dao.LogErrorDao;
import cn.xshi.log.model.*;
import cn.xshi.common.base.BaseUtils;
import cn.xshi.common.entity.OauthAccountEntity;
import cn.xshi.common.util.date.DateUtil;
import cn.xshi.log.client.util.IDGenerate;
import cn.xshi.log.client.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import nl.bitwalker.useragentutils.Browser;
import nl.bitwalker.useragentutils.OperatingSystem;
import nl.bitwalker.useragentutils.UserAgent;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
 * <p>
 * 系统日志
 * </p>
 *
 * @author dengcj
 * @since 2022-08-18
 */
@Component
@Slf4j
public class LogsUtil {

    @Resource
    IDGenerate idGenerate;

    @Resource
    BaseUtils baseUtils;

    @Resource
    LogErrorDao logErrorDao;
    
    /**
     * 登录日志
     * @param logLogin
     */
    public void loginLogs(LogLogin logLogin){
        try {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            logLogin.setIp(request.getRemoteAddr());
            UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
            Browser browser = userAgent.getBrowser();
            OperatingSystem os = userAgent.getOperatingSystem();
            logLogin.setBrowserName(browser.getName());
            logLogin.setBrowserType(browser.getBrowserType().getName());
            logLogin.setSystem(os.getName());
            logLogin.setId(""+idGenerate.nextId());
            logLogin.setCreateTime(new Date());
            if(null != userAgent.getBrowserVersion()){
                logLogin.setBrowserVersion(userAgent.getBrowserVersion().getVersion());
            }
            Runnable runnable = new LogLoginWorker(logLogin,request);
            Thread thread = new Thread(runnable);
            thread.start();
        }catch (Exception e){
            log.error("添加登录日志异常：{}-{}",e,logLogin);
        }
    }

    /**
     * 业务日志 （仅限于拦截器使用）
     * @param param 参数
     * @param batch 批次
     */
    public void addOpLog(String param,Long batch){
        //查询当前用户
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setMethod(request.getMethod());
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setParam(param);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setType(1);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+batch);
        LogOperateWorker logOperateWorker = new LogOperateWorker(logOperate,request);
        new Thread(logOperateWorker).start();
    }

    /**
     * 业务日志
     * @param message 执行描述
     */
    public void addOpLog(String message){
        //查询当前用户
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setMethod(request.getMethod());
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setResult(message);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setType(0);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+idGenerate.nextId());
        LogOperateWorker operateLogWorker = new LogOperateWorker(logOperate,request);
        new Thread(operateLogWorker).start();
    }

    /**
     * 业务日志
     * @param modules 模块
     * @param message 执行描述
     */
    public void addOpLog(String modules,String message){
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setMethod(request.getMethod());
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setModules(modules);
        logOperate.setResult(message);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setType(0);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+idGenerate.nextId());
        LogOperateWorker operateLogWorker = new LogOperateWorker(logOperate,request);
        new Thread(operateLogWorker).start();
    }

    /**
     * 业务日志
     * @param modules 执行描述
     * @param message 执行描述
     * @param parm 参数
     */
    public void addOpLog(String modules,String message,String parm){
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setMethod(request.getMethod());
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setModules(modules);
        logOperate.setResult(message);
        logOperate.setParam(parm);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setType(0);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+idGenerate.nextId());
        LogOperateWorker operateLogWorker = new LogOperateWorker(logOperate,request);
        new Thread(operateLogWorker).start();
    }

    /**
     * 执行变更记录
     * @param <T>
     * @param oldT
     * @param newT
     * @param modules
     * @param businessId
     */
    public <T> void aRecord(T oldT, T newT, String modules,String businessId){
        try {
            long batch = idGenerate.nextId();
            OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            JSONObject oldJson = JsonUtil.toJsonObj(oldT);
            JSONObject newJson = JsonUtil.toJsonObj(newT);
            List<LogModifyRecord> list = new ArrayList<LogModifyRecord>();
            Iterator iterator = oldJson.keys();
            while(iterator.hasNext()){
                String key = (String) iterator.next();
                String oldV = oldJson.getString(key);
                String newV = newJson.getString(key);
                if(!oldV.equals(newV)){
                    LogModifyRecord record = new LogModifyRecord();
                    record.setAfterValue(""+newV);
                    record.setBeforeValue(""+oldV);
                    record.setCreateTime(new Date());
                    record.setField(key);
                    record.setBusinessId(businessId);
                    record.setModules(modules);
                    record.setId(""+idGenerate.nextId());
                    record.setBatch(""+batch);
                    if(null != oauthAccountEntity){
                        record.setCreateId(oauthAccountEntity.getId());
                    }
                    record.setBatch(""+idGenerate.nextId());
                    list.add(record);
                }
            }
            LogModifyRecordWorker logModifyRecordWorker = new LogModifyRecordWorker(list,request);
            new Thread(logModifyRecordWorker).start();
        } catch (Exception e) {
            log.error("记录变更日志异常：{}",e);
        }
    }

    /**
     * 执行变更记录并过滤字段
     * @param <T>
     * @param oldT
     * @param newT
     * @param modules
     * @param business_id
     * @param fieldList
     */
    public <T> void aRecord(T oldT, T newT, String modules,String business_id,List<String> fieldList){
        try {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            JSONObject oldJson = cn.xshi.common.util.JsonUtil.toJsonObj(oldT);
            JSONObject newJson = cn.xshi.common.util.JsonUtil.toJsonObj(newT);
            List<LogModifyRecord> list = new ArrayList<LogModifyRecord>();
            Iterator iterator = oldJson.keys();
            while(iterator.hasNext()){
                String key = (String) iterator.next();
                if(!fieldList.isEmpty() && fieldList.size() > 0){
                    for(String field:fieldList){
                        if(field.equals(key)){
                            String oldV = oldJson.getString(key);
                            String newV = newJson.getString(key);
                            if(!oldV.equals(newV)){
                                LogModifyRecord record = new LogModifyRecord();
                                record.setAfterValue(""+newV);
                                record.setBeforeValue(""+oldV);
                                record.setCreateTime(DateUtil.getDate());
                                record.setField(key);
                                record.setModules(modules);
                                list.add(record);
                            }
                        }
                    }
                }
            }
            OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
            String userId = null;
            if(null != oauthAccountEntity){
                userId = oauthAccountEntity.getId();
            }
            for(int i = 0; i < list.size(); i++){
                list.get(i).setId(""+idGenerate.nextId());
                list.get(i).setBusinessId(business_id);
                list.get(i).setCreateId(userId);
            }
            LogModifyRecordWorker logModifyRecordWorker = new LogModifyRecordWorker(list,request);
            new Thread(logModifyRecordWorker).start();
        } catch (Exception e) {
        }
    }

    /**
     * 创建异常日志
     * @param logError
     */
    public void aLogError(LogError logError){
        try {
            //查询当前用户
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            logError.setCreateTime(new Date());
            logError.setId(""+idGenerate.nextId());
            OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
            if(null != oauthAccountEntity){
                logError.setCreateId(oauthAccountEntity.getId());
            }
            Runnable runnable = new LogErrorWorker(logError,request);
            Thread thread = new Thread(runnable);
            thread.start();
        }catch (Exception e){
            log.error("处理”异常“日志异常：{}-{}",e,logError);
        }
    }

    /**
     * 创建加载页面监控日志
     * @param logLoadinfo
     */
    public void aLogLoadinfo(LogLoadinfo logLoadinfo){
        try {
            //查询当前用户
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            logLoadinfo.setCreateTime(new Date());
            logLoadinfo.setId(""+idGenerate.nextId());
            OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
            if(null != oauthAccountEntity){
                logLoadinfo.setCreateId(oauthAccountEntity.getId());
            }
            Runnable runnable = new LogLoadinfoWorker(logLoadinfo,request);
            Thread thread = new Thread(runnable);
            thread.start();
        }catch (Exception e){
            log.error("处理”页面加载监控“日志异常：{}-{}",e,logLoadinfo);
        }
    }

    /**
     * 创建启动或关闭服务日志
     * @param logStartStop
     */
    public void aLogStartStop(LogStartStop logStartStop){
        try {
            //查询当前用户
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
            logStartStop.setCreateTime(new Date());
            logStartStop.setId(""+idGenerate.nextId());
            OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
            if(null != oauthAccountEntity){
                logStartStop.setCreateId(oauthAccountEntity.getId());
            }
            Runnable runnable = new LogStartStopWorker(logStartStop,request);
            Thread thread = new Thread(runnable);
            thread.start();
        }catch (Exception e){
            log.error("处理”服务启动或关闭“日志异常：{}-{}",e,logStartStop);
        }
    }

    /**
     * 添加平台业务操作日志通用 采用put方法目的不走事务控制
     * @param classname
     * @param method
     * @param message
     */
    public void aBLogs(String classname,String method,String message){
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setClassName(classname);
        logOperate.setMethod(method);
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setResult(message);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setType(0);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+idGenerate.nextId());
        LogOperateWorker operateLogWorker = new LogOperateWorker(logOperate,request);
        new Thread(operateLogWorker).start();
    }

    /**
     * 添加平台业务操作日志通用 采用put方法目的不走事务控制
     * @param classname
     * @param method
     * @param message
     * @param parm
     */
    public void aBLogs(String classname,String method,String message,String parm){
        OauthAccountEntity oauthAccountEntity = baseUtils.getCurrentAccountInfo();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) ra).getRequest();
        LogOperate logOperate = new LogOperate();
        logOperate.setClassName(classname);
        logOperate.setMethod(method);
        logOperate.setUri(request.getRequestURI());
        logOperate.setCreateTime(new Date());
        logOperate.setResult(message);
        logOperate.setId(""+idGenerate.nextId());
        logOperate.setParam(parm);
        logOperate.setType(0);
        if(null != oauthAccountEntity){
            logOperate.setCreateId(oauthAccountEntity.getId());
        }
        logOperate.setBatch(""+idGenerate.nextId());
        LogOperateWorker operateLogWorker = new LogOperateWorker(logOperate,request);
        new Thread(operateLogWorker).start();
    }

    /**
     * 异常日志
     * @param logError
     */
    public void aBLogError(LogError logError){
        logErrorDao.addLogError(logError);
    }
}
